package com.idol.logger.core.printer.file

import android.util.Log
import com.idol.logger.core.IdolManager
import com.idol.logger.core.printer.data.LoggerMo
import com.idol.logger.core.printer.iface.IdolPrinter
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.Executor
import java.util.concurrent.Executors

class IdolFilePrinter private constructor(
    private val path: String,           // The log save path.
    private val retentionTime: Long,    // The log retention time.
    service: Executor? = null           // threads pool.
) : IdolPrinter {

    companion object {
        private val lock = Any()

        @Volatile
        private var ins: IdolFilePrinter? = null

        /**
         * file printer
         * @param path              The log save path.
         * @param retentionTime     The log retention time.
         * @param executor          threads pool.
         */
        fun ins(path: String, retentionTime: Long, executor: Executor? = null) = ins ?: synchronized(lock) {
            ins ?: IdolFilePrinter(path, retentionTime, executor).also { ins = it }
        }
    }

    /**
     * threads pool.
     */
    private val executor: Executor = service ?: Executors.newSingleThreadExecutor()

    private val fileName by lazy { genFileName() }

    private val worker = IdolPrintWorker<LoggerMo>({ doPrint(it) }, executor, lock)

    private val writer = IdolFileWriter(path)

    init {
        if (retentionTime > 0) executor.execute { cleanExpiredLog() }
    }

    override fun print(level: Int, tag: String, printString: String) {
        if (!IdolManager.debug) return
        worker.put(LoggerMo(System.currentTimeMillis(), level, tag, printString)).start()
    }

    private fun doPrint(logMo: LoggerMo) {
        var isOk = false
        if (writer.ready(fileName)) isOk = writer.append(logMo.toString())
        if (!isOk && (IdolManager.debug || IdolManager.SELF_DEBUG)) {
            Log.d(IdolManager.GLOBAL_TAG, "Lost log！！！！Lost log！！！！\n$logMo")
        }
    }

    private fun genFileName() = SimpleDateFormat("yy-MM-dd", Locale.CHINA).also {
        it.timeZone = TimeZone.getDefault()
    }.run { "LOG-${format(Date(System.currentTimeMillis()))}.txt" }

    /**
     * Delete expired log files.
     */
    private fun cleanExpiredLog() {
        with(System.currentTimeMillis()) {
            File(path).listFiles { file ->
                this - file.lastModified() > retentionTime
            }?.forEach { it.delete() }
        }
    }

}